Installation

  • 全局安装:sudo npm install webpack -g

  • 项目安装:npm init; npm install webpack --save-dev

    简写形式:npm i webpack -D

  • "scripts": {
        "start": "webpack --config mywebpack.config.js"
    }
    

    上面是npm 配置webpack 的标准推荐配置

Intro

传统的Javascript tag 引入方式会带来一系列问题,如依赖不存在、依赖顺序错误,依赖引入但没有使用等。Webpack 为了解决这些问题,通过ES6 Module 来管理这些依赖。

尽管 import/export 语句在浏览器中还未被支持,你也可以正常的使用,因为 webpack 会将其替换为 ES5 兼容的代码。webpack 不会更改你的代码中除 import/export 以外的部分。如果你在使用其它 ES2015 特性,请确保你使用了一个像是 BabelBublé 的转译器。

Start

  • 创建index.html, entry.js, First.js, Second.js

  • 在index.html 中引入bundle.js

  • 在js中分别写入内容,并且在entry.js 中添加:

    import './First.js';
    import './Second.js'
    
  • 执行 webpack entry.js bundle.js (webpack [entry file] _ [bundle file]])

    我们把First 和Second 的内容引入了Entry,然后把Entry 打包 变成了bundle.js,完成打包工作!

    Webpack 会分析入口文件,解析包含依赖关系的各个文件。这些文件(模块)都打包到 bundle.js 。Webpack 会给每个模块(文件)分配一个唯一的 id 并通过这个 id 索引和访问模块。在页面启动时,会先执行 entry.js 中的代码,其它模块会在运行 require 的时候再执行。

  • 带配置的Webpack

    通过使用webpack.config.js 来配置webpack,从而可以直接输入webpack 来执行打包过程

    // webpack.config.js
    
    var path = require('path');
    
    module.exports = {
      entry: './app/entry.js',
      output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
      }
    };
    
  • 配合NPM 或Yarn 使用

    在package.json 中可以添加script: 'build': 'webpack'

    这样就可以通过 npm run build 来达到一样的效果

配置文件 webpack.config.js

无论是在require的时候编写我们loader的前缀,还是在我们的命令行中进根据扩展名来自动绑定我们的loader,显然都不够自动化,在需要编译的语言继续增加的情况下,显然会是一个噩梦。

所以我们需要一个配置文件来帮我们做这些事情,默认情况下,会搜索当前目录的 webpack.config.js 文件,这个文件是一个 node.js 模块,返回一个 json 格式的配置信息对象,或者通过 --config 选项来指定配置文件。如下

var Webpack = require("webpack");

module.exports = {
    entry: ["./entry.js"],
    output: {
        path: __dirname,
        filename: "bundle.js"
    },
    module: {
        loaders: [
            {
                test: /\.css$/,
                loader: "style!css"
            },
            {
                test: /\.scss$/,
                loader: "style!css!sass"
            }
        ]
    }
};

//在entry 中require 文件,直接执行webpack 即可
  • entry:指入口文件的配置项,它是一个数组的原因是webpack允许多个入口点。 当然如果你只有一个入口的话,也可以直接使用双引号"./entry.js"
  • output:配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称
  • module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。
    • /\.css$/会匹配 xx.css文件,但是并不适用于xx.sass或者xx.css.zip文件 /\.css/除了匹配xx.css也可以匹配xx.css.zip
    • 加载器后可以加入?xx=yy传递参数,表示添加将xx设置为yy(跟http地址Query很像) 如:loader: "url-loader?limit=8192"

Plugin

除了配置loader 以外,webpack 还提供了许多插件,在config 文件中的plugin 里实现 Webpack本身内置了一些常用的插件,还可以通过npm安装第三方插件。 下面测试一个内置的,用来给输出的文件头部添加注释信的内置插件 “BannerPlugin” 来实践插件的配置和运行。

var Webpack = require("webpack");//必须引入
module:{
},
plugins: [
    new Webpack.BannerPlugin("这里是打包文件头部注释!")//注意这是一个数组..
]

Code-Splitting

代码分离是webpack 的显著特性之一,你可以把你的代码分离到不同的 bundle 中,然后你就可以去按需加载这些文件,这样大大节省了加载的时间。

CSS 分离

  • 通过 CSS-loader 将 CSS 打包到 Javascript 文件中

    安装 css-loader 和 style-loader npm install --save-dev css-loader style-loader

    module.exports = {
        module: {
            rules: [{
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            }]
        }
    }
    

    这样 css 会和 Javascript 打包在一起,然后在初始加载后通过一个<style> 标签注入到网页中。

    这里有一个缺点就是,你无法使用浏览器的能力,去异步且并行去加载 CSS。取而代之的是,你的页面需要等待整个 JavaScript 文件加载完,才能进行样式渲染。

    Webpack 2 用 rules 取代了原有的 loader 系统,在这里 use 可以理解为之前的loader。同时,链式 loader 也被 use array 取代。

  • 使用 ExtractTextWebpackPlugin 单独打包css

    安装 ExtractTextWebpackPlugin npm install --save-dev extract-text-webpack-plugin

    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    module.exports = {
        module: {
             rules: [{
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: 'css-loader'
                })
             }]
         },
        plugins: [
            new ExtractTextPlugin('styles.css'),
        ]
    }
    

    上述配置会生成一个新的 CSS 文件,可以作为单独标签添加到 index.html 里。

三方库公用代码分离

我们的应用程序中,会有很多第三方工具代码,这些代码不经常改变,但是因为所有js 文件都会打包到一个文件中,每次改动代码时,这些工具代码也会被重新打包重新下载,浪费资源。

如果能把这些第三方不变的代码提取出来,这样文件会被缓存而不去再次请求cdn,这样保证了只有应用代码每次发生变化,而 vendor 代码保持缓存,减少了开销。我们通过插件 CommonsChunkPlugin 去实现这个功能。

CommonsChunkPlugin 从根本上允许我们从不同的 bundle 中提取所有的公共模块,并且将他们加入公共 bundle 中。如果公共 bundle 不存在,那么它将会创建一个出来。

var webpack = require('webpack');
var path = require('path');

module.exports = function() {
    return {
        entry: {
            main: './index.js'
          	//Notice we do not have an explicit vendor entry here
        },
        output: {
            filename: '[name].[chunkhash].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                minChunks: function (module) {
                   // this assumes your vendor imports exist in the node_modules directory
                   return module.context && module.context.indexOf('node_modules') !== -1;
                }
            }),
            //CommonChunksPlugin will now extract all the common modules from vendor and main bundles
            new webpack.optimize.CommonsChunkPlugin({
                name: 'manifest' //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
            })
        ]
    };
}

常用命令

  • webpack 最基本的启动webpack命令
  • webpack -w 提供watch方法,实时进行打包更新
  • webpack -p 构件生产环境,包括对打包后的文件进行压缩等
  • webpack -d 提供SourceMaps,方便调试
  • webpack —colors 输出结果带彩色,比如:会用红色显示耗时较长的步骤
  • webpack —profile 输出性能数据,可以看到每一步的耗时
  • webpack --display-modules 显示被隐藏的模块
  • webpack --progress —colors 热加载,可以看到进度和颜色

练习

图片加载

一般使用url-loader 去把图片以url 的形式在加载到js中,所以这里使用url-loader

npm i url-loader -D 添加两个div 在index.html,并在css 中为两个div添加background-image (几个宽高) 在config 文件里加入loader 信息,如下。 limit 指最大转换Base64 的容量,name 指转化好后生成的路径 运行 webpack

{
  test: /\.(png|jpg)$/,
    loader: "url?limit=8192&name=./img/[name].[ext]"
}

我们可以看到,在生成的页面中,小于8kb的图片都被缓存成了base64 的代码,而大于8kb的图片都被转移进了img文件夹

webpack-dev-server

webpack -w 实现了实时编译开发,但是还是需要浏览器刷新去实现,webpack 提供了webpack-dev-server 来实现live-load

  • 安装:npm install webpack-dev-server -g

  • 项目根目录下执行命令:webpack-dev-server

  • devServer: {
            historyApiFallback: true,
            hot: false,
            inline: true,
            grogress: true,
        }
    

这样,我们就可以在默认的http://localhost:8080/webpack-dev-server/ 网址上打开我们的 index.html 实现 live-load